package com.peas.platform.common.core.configuration;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.StrUtil;
import com.peas.platform.common.core.interceptor.BaseFeignInterceptor;
import com.peas.platform.common.core.utils.RequestUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author caizhh
 */
@Configuration
@Slf4j
public class AlphaFeignRequestInterceptor implements RequestInterceptor {

    @Value("${spring.application.name}")
    private String springApplicationName;

    @Resource
    private ApplicationContext ac;

    @SneakyThrows
    @Override
    public void apply(RequestTemplate requestTemplate) {
        StopWatch sw = new StopWatch();
        sw.start();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            log.debug("feign request interceptor, requestAttributes is null");
        } else {
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    if (StrUtil.isBlank(name)) {
                        continue;
                    }
                    Enumeration<String> values = request.getHeaders(name);
                    while (values.hasMoreElements()) {
                        String value = values.nextElement();
                        log.debug("header----name:" + name + ",value:" + value);
                        if (CollUtil.contains(RequestUtil.ignoreHeader, name.toLowerCase())) {
                            log.debug("[ignore header]----" + name + ":" + value);
                            break;
                        }
                        if (StrUtil.isNotBlank(value) && !StrUtil.contains(value, " ")) {
                            try {
                                log.debug("[set header]----" + name + ":" + value);
                                requestTemplate.header(name, value);
                            } catch (IllegalArgumentException e) {
                                //java.lang.IllegalArgumentException: an expression is required.
                                log.error("requestTemplate.header,name:" + name + ",value:" + value + ",IllegalArgumentException:" + e.getMessage(), e);
                            }
                        }
                    }
                }
            }
        }
        requestTemplate.header(RequestContextUtilEnum.application.name(), springApplicationName);
        requestTemplate.header(RequestContextUtilEnum.sso_sessionid.name(), RequestContextUtil.getCurrentSsoSessionId());
        requestTemplate.header(RequestContextUtilEnum.userId.name(), RequestContextUtil.getCurrentUserId());
        requestTemplate.header(RequestContextUtilEnum.userCode.name(), RequestContextUtil.getCurrentUserCode());
        requestTemplate.header(RequestContextUtilEnum.account.name(), RequestContextUtil.getCurrentAccount());
        requestTemplate.header(RequestContextUtilEnum.requestId.name(), RequestContextUtil.getCurrentRequestId());
        requestTemplate.header(RequestContextUtilEnum.resourceCode.name(), RequestContextUtil.getResourceCode());
        sw.stop();
        log.debug("feign request interceptor,header={}", requestTemplate.headers());
        log.debug("AlphaFeignRequestInterceptor.apply, all step used:" + sw.getTotalTimeMillis());
        List<BaseFeignInterceptor> list = getBaseFeignInterceptors();
        CollUtil.forEach(list, (CollUtil.Consumer<BaseFeignInterceptor>) (value, index) -> value.apply(requestTemplate));
    }

    private List<BaseFeignInterceptor> getBaseFeignInterceptors() {
        List<BaseFeignInterceptor> list = Collections.emptyList();
        Map<String, BaseFeignInterceptor> beans = ac.getBeansOfType(BaseFeignInterceptor.class);
        if (CollUtil.isNotEmpty(beans)) {
            list = new ArrayList<>(beans.values());
            list.sort((o1, o2) -> o1.sort() == null ? 1 : o2.sort() == null ? -1 : o1.sort().compareTo(o2.sort()));
        }
        return list;
    }

}
